﻿// Spun AJAX Framework
// Copyright (C) 2008 Blake Hegerle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;

namespace Spun.Communications.Hosting
{
    public class ServerHost : Host
    {
        /* Parameters: 
         *      HostString: Either Host.WILDCARD for any request, or a virtual-server name.
         *      Port: TCP port
         *      VirtualDirectory: The base directory for this host; this must not be nested within
         *          another vdir on this server (i.e. can't have /foo/ and /foo/bar/). No leading 
         *          or tailing slash.
         *      Servers: The keys should not have leading or tailing slashes. Empty string is allowed.
         *          These can be nested, so foo and foo/bar is okay.
         *          
         *      When the request comes in, slashes are removed, so http://localhost/VDir/SubDir and 
         *      http://localhost/VDir/SubDir/ are treated identically.
         */
        public ServerHost(string HostString,
            short Port,
            string VirtualDirectory,
            IDictionary<string, IServer> Servers)
            : base(HostString, Port, VirtualDirectory)
        {
            this.Servers = new Dictionary<string, IServer>(Servers, StringComparer.CurrentCultureIgnoreCase);

            VDirMatcher = new Regex("^/" + VirtualDirectory + "(|/([^/]*)(.*))$",
                         RegexOptions.IgnoreCase);
        }

        protected override void HandleRequest(HttpListenerContext Context)
        {
            string Path = Context.Request.Url.AbsolutePath;

            Match Match = VDirMatcher.Match(Path);

            if (Match.Success)
            {
                string RelativePath = Match.Groups[2].Value;
                RelativePath.Trim('/');

                IServer Server;

                if (Servers.TryGetValue(RelativePath, out Server))
                {
                    var ServerRelativePath = Match.Groups[3].Value.Trim('/');
                    Server.ProcessRequest(Context, ServerRelativePath);
                }
                else
                {
                    TextResponse(Context, 404, "Not found: " + Path);
                }
            }
            else
            {
                throw new Exception("Request outside virtual directory");
            }
        }

        private Regex VDirMatcher;
        private IDictionary<string, IServer> Servers;
    }
}
